home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / j109lxa4.tar / tipmail.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  11KB  |  471 lines

  1. /* "Dumb terminal" mailbox interface
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  *      May '91 Bill Simpson
  5.  *              move to separate file for compilation & linking
  6.  *      Sep '91 Bill Simpson
  7.  *              minor changes for DTR & RLSD
  8.  *      Jan '93 Doug Crompton
  9.  *              Mods to code to make it work with both terminal
  10.  *              and Modem. Timers and CD check revamped. Now Always
  11.  *              detects CD loss and timeouts work properly.
  12.  *              Setting Tiptimeout to 0 disables idle timeout
  13.  *      Feb '93 Added code to support Xmodem - RAW Serial DATA
  14.  *      Mar '93 Changed asy_send to asy_sen_wait, an internal function
  15.  *              To eliminate asyinc buffers from growing beyond control
  16.  *              and to stop data from flowing to serial device if CD is lost
  17.  *
  18.  * Command Syntax now : 'start tip <interface> <modem|terminal> [timeout sec]'
  19.  */
  20. #include "global.h"
  21. #include "config.h"
  22. #include "mbuf.h"
  23. #include "timer.h"
  24. #include "proc.h"
  25. #include "iface.h"
  26. #ifdef UNIX
  27. #include "unixasy.h"
  28. #else
  29. #include "i8250.h"
  30. #endif
  31. #include "asy.h"
  32. #include "socket.h"
  33. #include "usock.h"
  34. #include "telnet.h"
  35. #include "mailbox.h"
  36. #include "tipmail.h"
  37. #include "devparam.h"
  38. #include "lapb.h"
  39.  
  40. #ifdef TIPMAIL
  41. #ifdef ALLSERV
  42.  
  43. static void tip_in __ARGS((int dev,void *n1,void *n2));
  44. static void tipidle __ARGS((void *t));
  45. static int asy_send_wait __ARGS((int dev,int modem,struct mbuf *bp));
  46.  
  47. #define Tiptimeout 180;      /* Default tip inactivity timeout (seconds) */
  48.  
  49. /* Input process */
  50. static void
  51. tip_in(dev,n1,n2)
  52. int dev;
  53. void *n1,*n2;
  54. {
  55.     struct tipcb *tip;
  56.     struct mbuf *bp;
  57.     char *buf[2], line[MBXLINE];
  58.     int c, ret, pos = 0;
  59.  
  60.     tip = (struct tipcb *) n1;
  61.     
  62.     while((c = get_asy(dev)) != -1){
  63.       tip->firstwarn=1;
  64.       tip->timeout=tip->default_timeout;
  65.       Asy[dev].iface->lastrecv = secclock();
  66.       if (!tip->raw) {                  
  67.             c &= 0x7f;
  68.             ret = 0;
  69.             if(tip->echo == WONT){
  70.                 switch(c){
  71.                 case 18:        /* CTRL-R */
  72.                     bp = pushdown(qdata(line,pos),4);
  73.                     memcpy(bp->data,"^R\r\n",4);
  74.                     ret = 1;
  75.                     break;
  76.                 case 0x7f:      /* DEL */
  77.                 case '\b':
  78.                     bp = NULLBUF;
  79.                     if(pos){
  80.                         --pos;
  81.                         bp = qdata("\b \b",3);
  82.                     }
  83.                     ret = 1;
  84.                     break;
  85.                 case '\r':
  86.                     c = '\n';       /* CR => NL */
  87.                 case '\n':
  88.                     bp = qdata("\r\n",2);
  89.                     break;
  90.                 default:
  91.                     bp = pushdown(NULLBUF,1);
  92.                     *bp->data = c;
  93.                     break;
  94.                 }
  95.                 asy_send_wait(dev,tip->chk_modem_cd,bp);
  96.                 tip->iface->lastsent = secclock();
  97.                 if(ret)
  98.                     continue;
  99.             }
  100.             line[pos++] = c;
  101.             if(pos == MBXLINE - 1 || tip->echo == WILL
  102.                 || c == '\n'){
  103.                 line[pos] = '\0';
  104.                 pos = 0;
  105.                 usputs(tip->s,line);
  106.                 usflush(tip->s);
  107.             }
  108.            } else {
  109.              usputc(tip->s,c);
  110.              usflush(tip->s);
  111.            }
  112.     }
  113.     /* get_asy() failed, terminate */
  114.     close_s(tip->s);
  115.     tip->in = tip->proc;
  116.     tip->proc = Curproc;
  117.     buf[1] = Asy[dev].iface->name;
  118.     tip0(2,buf,NULL);
  119. }
  120. /* Start mailbox on serial line */
  121. int
  122. tipstart(argc,argv,p)
  123. int argc;
  124. char *argv[];
  125. void *p;
  126. {
  127.     register struct iface *ifp;
  128.     register struct asy *ap;
  129.     register struct tipcb *tip;
  130.     struct mbuf *bp, *dp, *op; /* op is output, dp is duplicate */
  131. #ifndef UNIX
  132.     struct fifo *fp; 
  133. #endif
  134.     char *buf[2];
  135.     int dev, c, i, off, cnt, cmd, s[2], type = TIP_LINK;
  136.  
  137.     if((ifp = if_lookup(argv[1])) == NULLIF){
  138.     tprintf(Badinterface,argv[1]);
  139.         return 1;
  140.     }
  141.     for(dev=0,ap = Asy;dev < ASY_MAX;dev++,ap++)
  142.         if(ap->iface == ifp)
  143.             break;
  144.     if(dev == ASY_MAX){
  145.         tprintf("Interface %s not asy port\n",argv[1]);
  146.         return 1;
  147.     }
  148.     if(ifp->raw == bitbucket){
  149.         tprintf("Tip session already active on %s\n",argv[1]);
  150.         return 1;
  151.     }
  152.     psignal(Curproc,0);     /* Don't keep the parser waiting */
  153.     chname(Curproc,"Mbox tip");
  154.     tip = (struct tipcb *) callocw(1,sizeof(struct tipcb));
  155.     
  156.     tprintf("Tip started on %s - ",argv[1]);
  157.     switch (argv[2][0]) {
  158.             case 'm':
  159.             case 'M':
  160.                   tip->chk_modem_cd=1;
  161.                   tprintf(" with");
  162.                   break;
  163.             default : tip->chk_modem_cd=0;
  164.                   tprintf(" without");
  165.      }
  166.      tprintf(" CD check - ");
  167.      if (argc>3)
  168.         tip->default_timeout=atoi(argv[3]);
  169.      else
  170.         tip->default_timeout=Tiptimeout;    
  171.      
  172.      if (tip->default_timeout)
  173.         tprintf("%d Second",tip->default_timeout);
  174.      else
  175.         tprintf("No");
  176.      tprintf(" Timeout\n");
  177.  
  178.     /* Save output handler and temporarily redirect output to null */
  179.     tip->asy_dev=dev;
  180.     tip->rawsave = ifp->raw;
  181.     ifp->raw = bitbucket;
  182.     tip->iface = ifp;
  183.     tip->proc = Curproc;
  184.     tip->timer.func = tipidle;
  185.     tip->timer.arg = (void *) tip;
  186.     tip->raw=0;
  187.     tip->next = Tiplist;
  188.     Tiplist = tip;
  189.     buf[1] = ifp->name;
  190.  
  191.     /* Suspend packet input drivers */
  192.     suspend(ifp->rxproc);
  193.     
  194.     for(;;) {
  195.         ifp->ioctl(ifp,PARAM_UP,TRUE,0L);
  196.         
  197.         /* Wait for DCD to be asserted if modem*/
  198.         if (tip->chk_modem_cd) {
  199.           pause(1000L);
  200.           while (! carrier_detect(tip->asy_dev))
  201.               pwait(NULL);
  202.           pause(1000L);
  203.         }
  204.         
  205.         if(socketpair(AF_LOCAL,SOCK_STREAM,0,s) == -1){
  206.             tprintf("Could not create socket pair, errno %d\n",errno);
  207.             tip0(2,buf,p);
  208.             return 1;
  209.         }
  210.         seteol(s[0],"\n");
  211.         seteol(s[1],"\n");
  212.         tip->echo = WONT;
  213.         tip->s = s[0];
  214.         if (tip->chk_modem_cd) {
  215.           log(tip->s,"Phone Mailbox Login");
  216.         }
  217.         newproc("mbx_incom",2048,mbx_incom,s[1],(void *)type,(void *)tip,0);
  218.  
  219.         /* check for line idle timeout and CD failure */
  220.         tip->firstwarn=1;
  221.         tip->timeout=tip->default_timeout;
  222.         set_timer(&tip->timer,1000L);
  223.         start_timer(&tip->timer);
  224.         
  225.         setflush(tip->s,-1);
  226.         sockmode(tip->s,SOCK_ASCII);
  227.  
  228.         /* Now fork into two paths, one rx, one tx */
  229. #ifndef UNIX
  230.         /* first clear (ignore) junk in asyinc input
  231.            which is always receiving - modem can garbage
  232.            on disconnect
  233.         */
  234.         fp = &ap->fifo;
  235.         fp->wp = fp->rp = fp->buf;
  236.         fp->cnt = 0;
  237. #endif
  238.         
  239.         tip->in = newproc("Mbox tip in",
  240.                 256,tip_in,dev,(void *)tip,NULL,0);
  241.         while((cnt = recv_mbuf(tip->s,&bp,0,NULL,0)) != -1) {
  242.            if(!tip->raw) {     
  243.             dup_p(&dp,bp,off=0,cnt); /* dup the whole pkt to pull */
  244.             for (i=0; i<cnt; i++)
  245.                switch(PULLCHAR(&dp)) {
  246.                case IAC:      /* ignore most telnet options */
  247.                   dup_p(&op,bp,off,i-off);
  248.                   asy_send_wait(dev,tip->chk_modem_cd,op);
  249.                   ifp->lastsent = secclock();
  250.  
  251.                   if((cmd = ++i < cnt ?  PULLCHAR(&dp) :
  252.                      recvchar(tip->s)) == -1)
  253.                      break;
  254.                   if(cmd > 250 && cmd < 255) {
  255.                       if((c = ++i < cnt ? PULLCHAR(&dp) :
  256.                           recvchar(tip->s)) == -1)
  257.                           break;
  258.                       switch(cmd){
  259.                       case WILL:
  260.                           if(c == TN_ECHO) {
  261.                               tip->echo = cmd;
  262.                               cmd = DO;
  263.                           }
  264.                           else
  265.                               cmd = DONT;
  266.                           break;
  267.                       case WONT:
  268.                           if(c == TN_ECHO)
  269.                               tip->echo = cmd;
  270.                           cmd = DONT;
  271.                           break;
  272.                       case DO:
  273.                       case DONT:
  274.                           cmd = WONT;
  275.                           break;
  276.                       }
  277.                       usprintf(tip->s,"%c%c%c",IAC,cmd,c);
  278.                       usflush(tip->s);
  279.                   }
  280.                   off = i + 1;
  281.                   break;
  282.             case '\r':
  283.                   if ( ++i < cnt &&  /* Skip NL but not IAC */
  284.                       (PULLCHAR(&dp) == IAC)) {
  285.                     dp = pushdown(dp,1);
  286.                     *dp->data = IAC;
  287.                     }
  288.                   break;
  289.             case '\n':
  290.                   dup_p(&op,bp,off,i-off);
  291.                   append(&op,qdata("\r\n",2));
  292.                   asy_send_wait(dev,tip->chk_modem_cd,op);
  293.                   ifp->lastsent = secclock();
  294.                   off = i + 1;
  295.                   break;
  296.              }
  297.  
  298.             (void)pullup(&bp,NULLCHAR,off);
  299.             asy_send_wait(dev,tip->chk_modem_cd,bp);
  300.              } else {
  301.             asy_send_wait(dev,tip->chk_modem_cd,bp);
  302.              }
  303.              ifp->lastsent = secclock();
  304.              tip->firstwarn=1;
  305.              tip->timeout=tip->default_timeout;
  306.              pwait(NULL);
  307.         }
  308.         stop_timer(&tip->timer);
  309.         pause(2000L);
  310.         close_s(tip->s);
  311.         killproc(tip->in);
  312.         tip->in=NULLPROC;
  313.       
  314.         pwait(itop(s[1])); /* let mailbox terminate, if necessary */
  315.         
  316.         /* Tell line to go down if modem*/
  317.         if (tip->chk_modem_cd) {
  318.         ifp->ioctl(ifp,PARAM_DOWN,TRUE,0L);
  319.         pause(5000L);
  320.         }
  321.         
  322.     }
  323. }
  324.  
  325. /* Send a message on the specified serial line  
  326.    Wait for queue to empty - for slow serial
  327.    lines where data flow control is desired
  328.    Eliminates large queue - I.E. memory hogging 
  329.    Stops data from flowing if CD is lost       */
  330.  
  331. static int
  332. asy_send_wait(dev,modem,bp)
  333. int dev;
  334. int modem;
  335. struct mbuf *bp;
  336.  
  337. {
  338.     if (carrier_detect(dev) || !modem) {
  339.         asy_send(dev,bp);
  340.         while (len_p((struct mbuf*)&Asy[dev].sndq)>1 
  341.             && (carrier_detect(dev) || !modem)){
  342.           pwait(NULL);
  343.         }
  344.     
  345.     } else {
  346.       free_p(bp);
  347.     }
  348.     return 0;
  349. }
  350.  
  351.  
  352.  
  353.  
  354.  
  355. int
  356. tip0(argc,argv,p)
  357. int argc;
  358. char *argv[];
  359. void *p;
  360. {
  361.     register struct iface *ifp;
  362.     struct tipcb *tip, *prev = NULLTIP;
  363.     struct proc *proc;
  364.  
  365.     if((ifp = if_lookup(argv[1])) == NULLIF){
  366.     tprintf(Badinterface,argv[1]);
  367.         return 1;
  368.     }
  369.     for(tip = Tiplist; tip != NULLTIP; prev = tip, tip = tip->next)
  370.         if(tip->iface == ifp) {
  371.             if(prev != NULLTIP)
  372.                 prev->next = tip->next;
  373.             else
  374.                 Tiplist = tip->next;
  375.             proc = tip->proc;
  376.             close_s(tip->s);
  377.             ifp->raw = tip->rawsave;
  378.             resume(ifp->rxproc);
  379.             stop_timer(&tip->timer);
  380.             killproc(tip->in);
  381.             free((char *)tip);
  382.             killproc(proc);
  383.             return 0;
  384.         }
  385.     return 0;
  386. }
  387. static void
  388. tipidle(t)
  389. void *t;
  390. {
  391.     struct tipcb *tip;
  392.     static char *msg1 = "Line idle - One minute to disconnect...\007\r\n";
  393.     static char *msg2 = "Disconnecting...\007\r\n";
  394.     tip = (struct tipcb *) t;
  395.  
  396.     if (! carrier_detect(tip->asy_dev) && tip->chk_modem_cd) {
  397.           close_s(tip->s);
  398.           return;
  399.     }
  400.     
  401.     if (--tip->timeout<=0 && tip->default_timeout!=0) {
  402.           if (tip->firstwarn) {
  403.           tip->iface->lastsent = secclock();
  404.           asy_send_wait(tip->iface->dev,tip->chk_modem_cd,
  405.                       qdata(msg1,(int16)strlen(msg1)));
  406.           tip->timeout=60;
  407.           start_timer(&tip->timer);
  408.           tip->firstwarn=0;
  409.           } else {
  410.           asy_send_wait(tip->iface->dev,tip->chk_modem_cd,
  411.                      qdata(msg2,(int16)strlen(msg2)));
  412.           close_s(tip->s);
  413.           }
  414.     } else {
  415.           start_timer(&tip->timer);
  416.     }
  417. }
  418.  
  419. #endif /*ALLSERV*/
  420. #endif /* TIPMAIL */
  421.  
  422. static int Stelnet = -1;
  423.  
  424. /* Start up Telnet server */
  425. int
  426. telnet1(argc,argv,p)
  427. int argc;
  428. char *argv[];
  429. void *p;
  430. {
  431.     struct sockaddr_in lsocket;
  432.     int s;
  433.  
  434.     if(Stelnet != -1){
  435.         return 0;
  436.     }
  437.     psignal(Curproc,0);     /* Don't keep the parser waiting */
  438.     chname(Curproc,"Telnet listener");
  439.  
  440.     lsocket.sin_family = AF_INET;
  441.     lsocket.sin_addr.s_addr = INADDR_ANY;
  442.     if(argc < 2)
  443.         lsocket.sin_port = IPPORT_TELNET;
  444.     else
  445.         lsocket.sin_port = atoi(argv[1]);
  446.     Stelnet = socket(AF_INET,SOCK_STREAM,0);
  447.     bind(Stelnet,(char *)&lsocket,sizeof(lsocket));
  448.     listen(Stelnet,1);
  449.     for(;;){
  450.         if((s = accept(Stelnet,NULLCHAR,(int *)NULL)) == -1)
  451.             break;  /* Service is shutting down */
  452.  
  453.     /* Low mem check now done in tcpin.c - WG7J */
  454.     /* Spawn a server */
  455.     newproc("mbox",2048,mbx_incom,s,(void *)TELNET_LINK,NULL,0);
  456.     }
  457.     return 0;
  458. }
  459. /* Stop telnet server */
  460. int
  461. telnet0(argc,argv,p)
  462. int argc;
  463. char *argv[];
  464. void *p;
  465. {
  466.     close_s(Stelnet);
  467.     Stelnet = -1;
  468.     return 0;
  469. }
  470.  
  471.